#ifndef _OBJECT_H
#define _OBJECT_H

#include "Common.h"
#include "String.h"

//ObjectFields
#define OBJECT_FIELD_GUID                         0x0000 // Size: 1, Type: INT, Flags: PUBLIC
#define OBJECT_FIELD_SERIAL                       0x0002 // Size: 1, Type: INT, Flags: PUBLIC
#define OBJECT_FIELD_SERVER                       0x0003 // Size: 1, Type: INT, Flags: PUBLIC
#define OBJECT_FIELD_TYPE                         0x0004 // Size: 1, Type: INT, Flags: PUBLIC
#define OBJECT_FIELD_ENTRY                        0x0005 // Size: 1, Type: INT, Flags: PUBLIC
#define OBJECT_FIELD_PADDING                      0x0006 // Size: 1, Type: INT, Flags: NONE
#define OBJECT_END 				  0x0007
#define OBJECT_STRING				  0xFFFF  
//====================================================================
//  Object
//  Base object for every item, unit, player, corpse, container, etc
//====================================================================

class SERVER_DECL Object 
{
public:
	Object();
	 virtual ~Object();

	//when using object pool contructor/destructor is not good to be called again sometimes. Use this instead
	virtual void Virtual_Constructor() {};
	virtual void Virtual_Destructor() {};
	int32 m_bufferPoolId;


	//! Get uint64 property
#ifdef USING_BIG_ENDIAN
        __inline const uint64 & GetUInt64Value( const uint16 & index ) const
#else
	WGSERVER_INLINE const uint64& GetUInt64Value( const uint16 & index ) const
#endif
	{
		ASSERT( index + uint32(1) < m_valuesCount );
#ifdef USING_BIG_ENDIAN
		/* these have to be swapped here :< */
		return uint64((uint64(m_uint32Values[index+1]) << 32) | m_uint32Values[index]);
#else
		return *((uint64*)&(m_uint32Values[ index ]));
#endif
	}

	//! Get int64 property
#ifdef USING_BIG_ENDIAN
        __inline const int64 & GetInt64Value( const uint16 & index ) const
#else
	WGSERVER_INLINE const int64& GetInt64Value( const uint16 & index ) const
#endif
	{
		ASSERT( index + uint32(1) < m_valuesCount );
#ifdef USING_BIG_ENDIAN
		/* these have to be swapped here :< */
		return int64((int64(m_uint32Values[index+1]) << 32) | m_uint32Values[index]);
#else
		return *((int64*)&(m_uint32Values[ index ]));
#endif
	}

	//! Get double property
	WGSERVER_INLINE const double& GetDoubleValue( const uint16 & index ) const
	{
		ASSERT( index < m_valuesCount );
		return *((double*)&(m_uint32Values[ index ])); 
	}

	//! Get float property
	WGSERVER_INLINE const float& GetFloatValue( const uint16 & index ) const
	{
		ASSERT( index < m_valuesCount );
		return m_floatValues[ index ];
	}
	
	WGSERVER_INLINE const uint32 & GetUint32Value(const uint16 & index) const
	{
		return m_uint32Values[index];
	}
	WGSERVER_INLINE const int32 & GetInt32Value(const uint16 & index) const
	{
		return m_int32Values[index];
	}

	WGSERVER_INLINE const String & GetStringValue(const uint16 & index) 
	{
		ASSERT(index < m_StringValues.size());
		return m_StringValues[index];
	}
	WGSERVER_INLINE void SetStringValue(const uint16 & index,const String & value)
	{
		ASSERT(index < m_StringValues.size());
		m_StringValues[index] = value;
	}

	WGSERVER_INLINE void  SetDataFieldFlag(const uint16 & index,const bool & flag)
	{
		ASSERT(index < m_DataFieldFlags.size());
		m_DataFieldFlags[index] = flag;
	}

	WGSERVER_INLINE const bool  GetDataFieldFlag(const uint16 & index)
	{
		ASSERT(index < m_DataFieldFlags.size());
		return m_DataFieldFlags[index];
	}
	
	WGSERVER_INLINE void  SetStringFieldFlag(const uint16 & index,const bool & flag)
	{
		ASSERT(index < m_StringFieldFlags.size());
		m_StringFieldFlags[index] = flag;
	}

	WGSERVER_INLINE const bool  GetStringFieldFlag(const uint16 & index)
	{
		 ASSERT(index < m_StringFieldFlags.size());
		 return m_StringFieldFlags[index];
	}

	void __fastcall ModFloatValue(const uint16 & index, const float & value );
	void ModSignedInt32Value(const uint16 & index, const int32 & value);
	void ModUnsigned32Value(const uint16 & index, const int32 & mod);
	uint32 GetModPUInt32Value(const uint16 & index, const int32 & value);

	//! Set uint32 property
	void SetByte(const uint16 & index, const uint8 & index1,const uint8 & value);

	WGSERVER_INLINE uint8 GetByte(const uint16 & i,const uint8 & i1)
	{
		ASSERT( i < m_valuesCount);
		ASSERT(i1 < 4);
#ifdef USING_BIG_ENDIAN
		return ((uint8*)m_uint32Values)[i*4+(3-i1)];
#else
		return ((uint8*)m_uint32Values)[i*4+i1];
#endif
	}

	void __fastcall SetByteFlag( const uint16 & index, uint8 offset, const uint8 & newFlag );
    	void __fastcall RemoveByteFlag( const uint16 & index, uint8 offset, const uint8 & newFlag );

	WGSERVER_INLINE bool HasByteFlag(const uint16 & index, const uint8 & index1, const uint8 & flag)
	{
		return ((GetByte(index, index1) & flag) != 0);
	}


	void EventSetUInt32Value(const uint16 & index, const uint32 & value);
	void __fastcall SetUInt32Value( const uint16 & index, const uint32 & value );
	void __fastcall SetInt32Value( const uint16 & index, const int32 & value );

	//! Set uint64 property
	void __fastcall SetUInt64Value( const uint16 & index, const uint64 & value );

	//! Set int64 property
	void __fastcall SetInt64Value( const uint16 & index, const int64 & value );
	
	//! Set double property
	void __fastcall SetDoubleValue( const uint16 & index, const double & value );
	
	//! Set float property
	void __fastcall SetFloatValue( const uint16 & index, const float & value );

	void __fastcall SetFlag( const uint16 & index, const uint32 & newFlag );

	void __fastcall RemoveFlag( const uint16 & index, const uint32 & oldFlag );

	WGSERVER_INLINE bool HasFlag( const uint16 & index, const uint32 & flag ) const
	{
		ASSERT( index < m_valuesCount );
		return (m_uint32Values[ index ] & flag) != 0;
	}

	//! Fill values with data from a space separated string of uint32s.
	size_t LoadValues(const char* data);

	void  ReserveValuesBuffer(const size_t & size);
	void  ReserveStringsBuffer(const size_t & size);
	void  ClearValues(void);
	void  ClearFlags(void);

	WGSERVER_INLINE uint16 GetValuesCount() const { return m_valuesCount; }
	
	WGSERVER_INLINE	uint16 GetStringCount() const { return (uint16) m_StringValues.size() ;}


	//clone the obj data	
	void clone(Object * obj);
protected:

	//! Object properties.
	union {
		uint32* m_uint32Values;
		int32* m_int32Values;
		float* m_floatValues;
	};

	//! Number of properties
	uint16 m_valuesCount;

	std::vector<String>	m_StringValues;

	std::vector<bool>	m_StringFieldFlags;
	std::vector<bool>	m_DataFieldFlags;

private:

};


#endif


